// Copyright (c) 2007 Robin Boerdijk. All rights reserved.
//
// This software is licensed under the terms of the Microsoft Reciprocal License as described 
// in the file LICENSE.txt, which you should have received as part of this distribution. The 
// license terms are also available at http://www.opensource.org/licenses/ms-rl.html.

#include "wtkpc.h"

#include "wtk/Menu.h"
#include "wtk/MenuCommand.h"
#include "wtk/SubMenu.h"
#include "wtk/win32.h"

#include <stdexcept>

namespace wtk
{
	Menu::Menu()
		: handle(NULL)
	{
	}

	HMENU Menu::CreateMenu()
	{
		return win32::CreateMenu();
	}

	void Menu::Create()
	{
		if (this->handle == NULL) {
			this->handle = CreateMenu();
			try {
				MENUINFO menuInfo;
				menuInfo.cbSize = sizeof(menuInfo);
				menuInfo.fMask = MIM_STYLE;
				menuInfo.dwStyle = MNS_NOTIFYBYPOS;
				win32::SetMenuInfo(this->handle, &menuInfo);

				for (UINT i = 0, n = this->items.size(); i < n; i++) {
					MenuItem *menuItem = this->items[i];
					MENUITEMINFOW menuItemInfo;
					menuItemInfo.cbSize = sizeof(menuItemInfo);
					menuItemInfo.fMask = MIIM_FTYPE;
					if (menuItem == NULL) {
						menuItemInfo.fType = MFT_SEPARATOR;
					} else {
						menuItemInfo.fType = MFT_STRING;
						menuItemInfo.fMask |= MIIM_STRING;
						menuItemInfo.dwTypeData = const_cast<LPWSTR>(menuItem->title.c_str());
						HMENU subMenuHandle = menuItem->GetSubMenuHandle();
						if (subMenuHandle == NULL) {
							menuItemInfo.fMask |= MIIM_DATA;
							menuItemInfo.dwItemData = reinterpret_cast<LONG_PTR>(menuItem);
						} else {
							menuItemInfo.fMask |= MIIM_SUBMENU;
							menuItemInfo.hSubMenu = subMenuHandle;
						}
					}
					try {
						win32::InsertMenuItemW(this->handle, i, TRUE, &menuItemInfo);
					} catch (...) {
						if (menuItemInfo.fMask & MIIM_SUBMENU) {
							win32::DestroyMenu(menuItemInfo.hSubMenu);
						}
						throw;
					}
				}
			} catch (...) {
				win32::DestroyMenu(this->handle);
				this->handle = NULL;
				throw;
			}
		}
	}

	void Menu::Destroy()
	{
		if (this->handle != NULL) {
			win32::DestroyMenu(this->handle);
			this->handle = NULL;
		}
	}
}
